package graph;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.LogarithmicAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.statistics.BoxAndWhiskerCategoryDataset;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;
import org.jfree.data.xy.XYBarDataset;
import org.jfree.data.xy.XYDataset;

import benchmarks.Benchmark;

import com.google.caliper.Param;
import com.google.caliper.Scenario;
import com.google.caliper.ScenarioResult;

public class ChartCreator {
	
	//TODO van stackoverflow
	//  http://stackoverflow.com/questions/285955/java-get-the-newest-file-in-a-directory
	public static File lastFileModified(String dir) { 
		File fl = new File(dir);
		File[] files = fl.listFiles(new FileFilter() {			
			public boolean accept(File file) {
				return file.isFile();
			}
		});
		long lastMod = Long.MIN_VALUE;
		File choise = null;
		for (File file : files) {
			if (file.lastModified() > lastMod && file.getName().endsWith(".json")) {
				choise = file;
				lastMod = file.lastModified();
			}
		}
		return choise;
	}
	
//	static public void createBarChart(String benchmarkName,
//			String[] libraries, String filePath) {
//		Map<String, Double> results = new ResultsParser(filePath).parse(
//				benchmarkName, libraries);
//		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
//		for (Map.Entry<String, Double> entry : results.entrySet()) {
//			dataset.setValue(entry.getValue(), benchmarkName, entry.getKey());
//		}
//		JFreeChart chart = ChartFactory.createBarChart3D(benchmarkName,
//				"Library", "ns", dataset, PlotOrientation.VERTICAL, true, true,
//				true);
//		try {
//			ChartUtilities.saveChartAsJPEG(new File(
//					"C:/Users/Blacky/workspace/Caliper/examples/"
//							+ benchmarkName + ".JPEG"), chart, 500, 300);
//		} catch (IOException e) {
//			System.err.println("Problem occurred creating chart.");
//		}
//	}

	static public void createBarChart(String[] benchmarks, String[] libraries, String filePath) {
		
		Map<String[], Double> results = new ResultsParser(filePath).parse(benchmarks, libraries);
		
		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
		for (Map.Entry<String[], Double> entry : results.entrySet()) {
			dataset.setValue(entry.getValue(), entry.getKey()[1], entry.getKey()[0]);
		}
				
		JFreeChart chart = ChartFactory.createBarChart3D("All",
				"Library", "ns", dataset, PlotOrientation.VERTICAL, true, true,
				true);

        final CategoryPlot plot = chart.getCategoryPlot();
        final LogAxis rangeAxis = new LogAxis("ns");
        rangeAxis.setRange(50, 130000);
      
        
        plot.setRangeAxis(rangeAxis);
        

		try {
			ChartUtilities.saveChartAsJPEG(new File(
					filePath + "Chart" + ".JPEG"), chart, 1200, 600);
		} catch (IOException e) {
			System.err.println("Problem occurred creating chart.");
		}
	}
	
	private static void createBoxAndWhiskerChart(String[] benchmarks, String[] libraries, String filePath) {
		
		Map<String[], List<Double>> results = new ResultsParser(filePath).parseAndGetList(benchmarks, libraries);
		
		DefaultBoxAndWhiskerCategoryDataset dataset = new DefaultBoxAndWhiskerCategoryDataset();
		
		for (Entry<String[], List<Double>> entry : results.entrySet()) {
			dataset.add(entry.getValue(), entry.getKey()[1], entry.getKey()[0]);
		}
		JFreeChart chart = ChartFactory.createBoxAndWhiskerChart("All",
				"Library", "ns", dataset, true);
		try {
			ChartUtilities.saveChartAsJPEG(new File(
					filePath + "BoxAndWhiskerChart" + ".JPEG"), chart, 1200, 600);
		} catch (IOException e) {
			System.err.println("Problem occurred creating chart.");
		}
	}

	public static void createBoxAndWhiskerChartLastModified(String[] benchmarks, String[] libraries, String filePath) {
		createBoxAndWhiskerChart(benchmarks, libraries, filePath + lastFileModified(filePath).getName());
	}
	
	public static void createBarChartLastModified(String[] benchmarks, String[] libraries, String filePath) {
		createBarChart(benchmarks, libraries, filePath + lastFileModified(filePath).getName());
	}
		


	public static void main(String[] args) throws Exception {
		final String[] benchmarkLibraries = Benchmark.class.getDeclaredField("library").getAnnotation(Param.class).value();
		
//		createBarChartLastModified(Benchmark.benchmarkMethods, benchmarkLibraries, Benchmark.resultsPath);
		//createBoxAndWhiskerChartLastModified(Benchmark.benchmarkMethods, benchmarkLibraries, Benchmark.resultsPath);
		//createBarChartLastModified(Benchmark.benchmarkMethods, new String[] {"GSonLib", "KryoLib", "ProtostuffLib"}, Benchmark.resultsPath);
//		ResultsParser a = new ResultsParser("C:/Users/Blackline/workspace/bachtest/Results/benchmarks.Benchmark.2012-11-21T22-10-09+0000.json");
//		for (Map.Entry<Scenario, ScenarioResult> entry : a.result.getRun().getMeasurements().entrySet()) {
//			System.out.println(entry.getKey().getVariables().containsValue("TXTCopy"));
//			System.out.println(entry.getKey().getVariables());
//		}
		
		new ResultsParser(Benchmark.resultsPath + lastFileModified(Benchmark.resultsPath).getName()).print("TXTDeserialization", "ProtostuffLib");

	}

}
